package cn.btks.commonserver.util;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import org.geotools.data.*;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.shapefile.dbf.DbaseFileHeader;
import org.geotools.data.shapefile.dbf.DbaseFileReader;
import org.geotools.data.shapefile.files.ShpFiles;
import org.geotools.data.shapefile.shp.ShapefileReader;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @Author lijun
 * @Date 2020/12/16 20:25
 */
public class GeoUtils {

    /**
     * 读shp文件（图形信息+属性信息）的写法：
     * @param filePath
     */
    public static void readSHP(String filePath) {
        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
        try {
            ShapefileDataStore sds = (ShapefileDataStore)dataStoreFactory.createDataStore(new File(filePath).toURI().toURL());
            sds.setCharset(Charset.forName("utf-8"));
            SimpleFeatureSource featureSource = sds.getFeatureSource();
            SimpleFeatureIterator itertor = featureSource.getFeatures().features();

            while(itertor.hasNext()) {
                SimpleFeature feature = itertor.next();
                Iterator<Property> it = feature.getProperties().iterator();

                while(it.hasNext()) {
                    Property pro = it.next();
                    System.out.println(pro);
                    JSONObject jsonObject = new JSONObject();
                }
            }
            itertor.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void readDBFVoid(String filePath) {
        try {
            FileChannel in = new FileInputStream(filePath).getChannel();
            DbaseFileReader dbfReader =  new DbaseFileReader(in, false,  Charset.forName("utf-8"));
            DbaseFileHeader header = dbfReader.getHeader();
            int fields = header.getNumFields();

            while ( dbfReader.hasNext() ){
                DbaseFileReader.Row row =  dbfReader.readRow();
//              System.out.println(row.toString());
                JSONObject jsonObject = new JSONObject();
                for (int i=0; i<fields; i++) {
                    System.out.println(header.getFieldName(i) + " : " + row.read(i));
                }
            }
            dbfReader.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static JSONArray readDBFJson(String filePath) {
        JSONArray jsonArray = new JSONArray();
        try {
            FileChannel in = new FileInputStream(filePath).getChannel();
            DbaseFileReader dbfReader =  new DbaseFileReader(in, false,  Charset.forName("utf-8"));
            DbaseFileHeader header = dbfReader.getHeader();
            int fields = header.getNumFields();

            while ( dbfReader.hasNext() ){
                DbaseFileReader.Row row =  dbfReader.readRow();
//              System.out.println(row.toString());
                JSONObject jsonObject = new JSONObject();
                for (int i=0; i<fields; i++) {
                    System.out.println(header.getFieldName(i) + " : " + row.read(i));
                    jsonObject.put(header.getFieldName(i), row.read(i));
                }
                jsonArray.add(jsonObject);
                jsonObject = null;
            }
            dbfReader.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonArray;
    }

    /**
     * 获取 shpfile 文件属性
     * @return
     */
    public static JSONArray getShpFileAttributes(String filePath)  {
        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
        JSONArray jsonArray = new JSONArray();
        try {
            ShapefileDataStore sds = (ShapefileDataStore)dataStoreFactory.createDataStore(new File(filePath).toURI().toURL());
            sds.setCharset(Charset.forName("utf-8"));
            SimpleFeatureSource featureSource = sds.getFeatureSource();
            // 提取出属性的 ID 值
            List<String> attributeID = new LinkedList<>();
            List<AttributeDescriptor> attrList= featureSource.getSchema().getAttributeDescriptors();
            for(AttributeDescriptor attr : attrList){
                String ID = attr.getName().getLocalPart();
//                if( !ID.equals("the_geom")){
//                    attributeID.add(ID);
//                }
                attributeID.add(ID);
            }
            SimpleFeatureCollection featureCollection = featureSource.getFeatures();
            SimpleFeatureIterator featureIterator = featureCollection.features();

            while (featureIterator.hasNext()) {
                SimpleFeature feature = featureIterator.next();
                JSONObject jsonObject = new JSONObject();
                List<Object> list = feature.getAttributes();
                for(int k = 0; k < list.size(); k++ ){
                    jsonObject.put(attributeID.get(k), list.get(k));
                }
                String s = jsonObject.toJSONString();
//                System.out.println(s);
                jsonArray.add(jsonObject);
                jsonObject = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonArray;
    }

    public static void writeSHP(String filepath) {
        try {
            //创建shape文件对象
            File file = new File(filepath);
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            params.put( ShapefileDataStoreFactory.URLP.key, file.toURI().toURL() );
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            //定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(DefaultGeographicCRS.WGS84);
            tb.setName("shapefile");
            tb.add("the_geom", Point.class);
            tb.add("POIID", Long.class);
            tb.add("NAMEC", String.class);
            ds.createSchema(tb.buildFeatureType());
            ds.setCharset(Charset.forName("utf-8"));
            //设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
            //写下一条
            SimpleFeature feature = writer.next();
            feature.setAttribute("the_geom", new GeometryFactory().createPoint(new Coordinate(116.123, 39.345)));
            feature.setAttribute("POIID", 1234567890l);
            feature.setAttribute("NAMEC", "某兴趣点1");
            feature = writer.next();
            feature.setAttribute("the_geom", new GeometryFactory().createPoint(new Coordinate(116.456, 39.678)));
            feature.setAttribute("POIID", 1234567891l);
            feature.setAttribute("NAMEC", "某兴趣点2");
            writer.write();
            writer.close();
            ds.dispose();

            //读取刚写完shape文件的图形信息
            ShpFiles shpFiles = new ShpFiles(filepath);
            ShapefileReader reader = new ShapefileReader(shpFiles, false, true, new GeometryFactory(), false);
            try {
                while (reader.hasNext()) {
                    System.out.println(reader.nextRecord().shape());
                }
            } finally {
                reader.close();
            }
        } catch (Exception e) { }
    }

    public static void transShape(String srcfilepath, String destfilepath) {
        try {
            //源shape文件
            ShapefileDataStore shapeDS = (ShapefileDataStore) new ShapefileDataStoreFactory().createDataStore(new File(srcfilepath).toURI().toURL());
            //创建目标shape文件对象
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            FileDataStoreFactorySpi factory = new ShapefileDataStoreFactory();
            params.put(ShapefileDataStoreFactory.URLP.key, new File(destfilepath).toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) factory.createNewDataStore(params);
            // 设置属性
            SimpleFeatureSource fs = shapeDS.getFeatureSource(shapeDS.getTypeNames()[0]);
            //下面这行还有其他写法，根据源shape文件的simpleFeatureType可以不用retype，而直接用fs.getSchema设置
            ds.createSchema(SimpleFeatureTypeBuilder.retype(fs.getSchema(), DefaultGeographicCRS.WGS84));

            //设置writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);

            //写记录
            SimpleFeatureIterator it = fs.getFeatures().features();
            try {
                while (it.hasNext()) {
                    SimpleFeature f = it.next();
                    SimpleFeature fNew = writer.next();
                    fNew.setAttributes(f.getAttributes());
                    writer.write();
                }
            } finally {
                it.close();
            }
            writer.close();
            ds.dispose();
            shapeDS.dispose();
        } catch (Exception e) { e.printStackTrace();    }
    }
}
